﻿// Copyright (c) 2012-2013 fancidev
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Util.Forms
{
    public static class GraphicsExtensions
    {
        /// <summary>
        /// Draws an image at the center of the given rectangle, shrinking
        /// the image proportionally if its with or height exceeds that of
        /// the rectangle.
        /// </summary>
        /// <param name="graphics">The graphics to draw on.</param>
        /// <param name="image">The image to draw.</param>
        /// <param name="bounds">The bounding rectangle.</param>
        public static void DrawImageCenteredAndFitted(
            this Graphics graphics, Image image, Rectangle bounds)
        {
            // Fit the image into the rectangle, keeping scale.
            Size sz = image.Size;
            if (sz.Width > bounds.Width)
            {
                sz.Height = sz.Height * bounds.Width / sz.Width;
                sz.Width = bounds.Width;
            }
            if (sz.Height > bounds.Height)
            {
                sz.Width = sz.Width * bounds.Height / sz.Height;
                sz.Height = bounds.Height;
            }
            bounds.X += (bounds.Width - sz.Width) / 2;
            bounds.Y += (bounds.Height - sz.Height) / 2;
            bounds.Width = sz.Width;
            bounds.Height = sz.Height;

            // Draw the bitmap.
            graphics.DrawImage(image, bounds);
        }

        /// <summary>
        /// Draws a rectangle, making sure it looks as expected.
        /// </summary>
        /// <param name="graphics">The graphics to draw on.</param>
        /// <param name="pen">The pen. Its Alignment property should be set
        /// to Inset to produce well-behaved output.</param>
        /// <param name="rect">The rectangle.</param>
        /// <remarks>
        /// The <code>Graphics.DrawRectangle</code> method has the weird
        /// behavior that when the pen width is 1.0, the right and lower
        /// borders of the rectangle are not drawn. This method fixes this
        /// problem.
        /// </remarks>
        public static void DrawRectangleAccurately(
            this Graphics graphics, Pen pen, Rectangle rect)
        {
            // Special hack if pen width is 1. I don't know why but if
            // we don't do this the frame will not be drawn correctly.
            if (pen.Width <= 1.0)
            {
                --rect.Width;
                --rect.Height;
            }
            graphics.DrawRectangle(pen, rect);
        }
    }
}
